package com.base.component.app.pay.weixin;

import java.io.IOException;

import com.base.component.app.pay.core.PayHandler;
import com.gitee.magic.core.exception.ApplicationException;
import com.gitee.magic.framework.head.utils.IoUtils;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.QueryOrderByOutTradeNoRequest;
import com.wechat.pay.java.service.payments.model.Transaction;

import jakarta.servlet.http.HttpServletRequest;

/**
 * 微信支付
 * 
 * @author mac
 *
 */
public abstract class WeixinBasePayHandler<P,T> implements PayHandler<P,T> {
	
	protected String appId;
	protected String merchantId;
	protected String privateKey;
	protected String merchantSerialNumber;
	protected String apiV3Key;
	protected String weixinPayDomain;
	protected HttpServletRequest request;
	
	public Config getConfig() {
		Config config = new RSAAutoCertificateConfig.Builder().merchantId(merchantId)
				.privateKey(privateKey).merchantSerialNumber(merchantSerialNumber)
				.apiV3Key(apiV3Key).build();
		return config;
	}
	
	public <R>R parseNotify(Class<R> prop) {
		String content;
		try {
			content = new String(IoUtils.inputStreamConvertBytes(request.getInputStream(), -1));
		} catch (IOException e) {
			throw new ApplicationException(e);
		}
		Config config = getConfig();
		
		String timestamp = request.getHeader("Wechatpay-Timestamp");
		String nonce = request.getHeader("Wechatpay-Nonce");
		String signature = request.getHeader("Wechatpay-Signature");
		String singType = request.getHeader("Wechatpay-Signature-Type");
		String number = request.getHeader("Wechatpay-Serial");
		NotificationParser parser = new NotificationParser((NotificationConfig) config);
		RequestParam requestParam = new RequestParam.Builder()
				.nonce(nonce)
				.signature(signature)
				.signType(singType)
				.timestamp(timestamp)
				.serialNumber(number)
				.body(content).build();
		return parser.parse(requestParam, prop);
	}
	
	public Transaction queryOrderByOutTradeNo(String outTradeNo) {
		Config config =getConfig();
		JsapiService service=new JsapiService.Builder().config(config).build();
        QueryOrderByOutTradeNoRequest request=new QueryOrderByOutTradeNoRequest();
        request.setOutTradeNo(outTradeNo);
        request.setMchid(merchantId);
        return service.queryOrderByOutTradeNo(request);
    }

	@Override
	public boolean verify() {
		Transaction transaction = parseNotify(Transaction.class);
		return Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState());
	}
	
}
